using LibraryManagementSystem.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;

namespace LibraryManagementSystem.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    [Authorize]
    public class BorrowController : ControllerBase
    {
        private readonly LibraryContext _context;

        public BorrowController(LibraryContext context)
        {
            _context = context;
        }

        // POST: api/borrow/borrowbook
        [HttpPost("borrowbook")]
        public async Task<IActionResult> BorrowBook(int libraryItemId)
        {
            int memberId = int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier));
            var member = await _context.Members.FindAsync(memberId);
            if (member == null)
            {
                return NotFound("Member not found.");
            }

            var libraryItem = await _context.Libraryitems.FindAsync(libraryItemId);
            if (libraryItem == null)
            {
                return NotFound("Library item not found.");
            }

            if (libraryItem.AvailableCopies <= 0)
            {
                return BadRequest("No available copies for this item.");
            }

            var borrowRecord = new Borrowrecord
            {
                MemberId = memberId,
                LibraryItemId = libraryItemId,
                BorrowDate = DateTime.UtcNow,
                DueDate = DateTime.UtcNow.AddDays(14),
                Status = "Borrowed"
            };

            libraryItem.AvailableCopies--;

            _context.Borrowrecords.Add(borrowRecord);
            await _context.SaveChangesAsync();

            return Ok("Book borrowed successfully.");
        }

        // POST: api/borrow/returnbook
        [HttpPost("returnbook")]
        public async Task<IActionResult> ReturnBook(int borrowRecordId)
        {
            var borrowRecord = await _context.Borrowrecords
                .Include(br => br.LibraryItem)
                .FirstOrDefaultAsync(br => br.Id == borrowRecordId);

            if (borrowRecord == null)
            {
                return NotFound("Borrow record not found.");
            }

            if (borrowRecord.Status != "Borrowed")
            {
                return BadRequest("This book has already been returned.");
            }

            borrowRecord.ReturnDate = DateTime.UtcNow;
            borrowRecord.Status = "Returned";

            if (borrowRecord.ReturnDate > borrowRecord.DueDate)
            {
                var overdueDays = (borrowRecord.ReturnDate.Value - borrowRecord.DueDate).Days;
                borrowRecord.Fine = overdueDays * 1.0m;
            }

            borrowRecord.LibraryItem.AvailableCopies++;

            await _context.SaveChangesAsync();

            return Ok(new
            {
                Message = "Book returned successfully.",
                Fine = borrowRecord.Fine
            });
        }

        // GET: api/borrow/history
        [HttpGet("history")]
        public async Task<ActionResult<IEnumerable<Borrowrecord>>> GetBorrowHistory()
        {
            int memberId = int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier));
            var member = await _context.Members
                .Include(m => m.Borrowrecords)
                .ThenInclude(br => br.LibraryItem)
                .FirstOrDefaultAsync(m => m.Id == memberId);

            if (member == null)
            {
                return NotFound("Member not found.");
            }

            return Ok(member.Borrowrecords);
        }

        // POST: api/borrow/reserve
        [HttpPost("reserve")]
        public async Task<IActionResult> ReserveBook(int libraryItemId)
        {
            int memberId = int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier));
            var member = await _context.Members.FindAsync(memberId);
            if (member == null)
            {
                return NotFound("Member not found.");
            }

            var libraryItem = await _context.Libraryitems.FindAsync(libraryItemId);
            if (libraryItem == null)
            {
                return NotFound("Library item not found.");
            }

            if (libraryItem.AvailableCopies > 0)
            {
                return BadRequest("This item is currently available and does not need to be reserved.");
            }

            var reservation = new Reservation
            {
                MemberId = memberId,
                LibraryItemId = libraryItemId,
                ReserveDate = DateTime.UtcNow,
                Status = "Active"
            };

            _context.Reservations.Add(reservation);
            await _context.SaveChangesAsync();

            return Ok("Reservation created successfully.");
        }

        // GET: api/borrow/report
        [HttpGet("report")]
        public async Task<IActionResult> GenerateBorrowReport()
        {
            var report = await _context.Borrowrecords
                .Include(br => br.LibraryItem)
                .Include(br => br.Member)
                .GroupBy(br => br.Status)
                .Select(g => new
                {
                    Status = g.Key,
                    Count = g.Count(),
                    TotalFine = g.Sum(br => br.Fine)
                })
                .ToListAsync();

            return Ok(report);
        }
    }
}